#include "Any.hpp"
#include "Log.h"
#include "buffer.h"
#include <Connection.h>
#include <cassert>
#include <cstdint>
#include <functional>
#include <memory>
#include <sys/types.h>
#include <unistd.h>
#include <EventLoop.h>

namespace muduo{
    // ============================Connection private============================
    void Connection::HandleRead(){
        // 将收到的数据存储到接收缓冲区，并调用message回调函数
        char buffer[65535]={0};
        ssize_t ret = _socket.NonBlockRecv(buffer, sizeof(buffer));
        if(ret < 0){
            // 代码中使用ShutdownInLoop可能会有线程安全问题
            debuglog<<"in shutdown";
            return ShutdownInLoop();
        }
        _inbuffer.WriteAndPush(buffer, ret);
        if(_inbuffer.EnableReadSize()>0){
            // 如果有数据可读，调用信息处理回调函数
            _message_callback(shared_from_this(),&_inbuffer);
        }
    }
    void Connection::HandleWrite(){
        // 将发送缓冲区的数据发送
        ssize_t ret = _socket.NonBlockSend(_outbuffer.GetReadIndex(), _outbuffer.EnableReadSize());
        if(ret < 0){
            // 发送失败
            if(_inbuffer.EnableReadSize()>0){
                _message_callback(shared_from_this(),&_inbuffer);
            }
            return Release();
        }
        // 发送完毕之后要更改发送缓冲区的读指针位置
        _outbuffer.MoveReadidx(ret);
        if(_outbuffer.EnableReadSize() == 0){
            // 关闭写事件监控
            _channel.CloseWrite();
            if(_statu == DISCONNECTING){
                Release();
            }
        }

    }
    void Connection::HandleClose(){
        infolog << "In HandleClose";
        if(_inbuffer.EnableReadSize()>0){
            _message_callback(shared_from_this(),&_inbuffer);
        }
        Release();
    }
    void Connection::HandleError(){
        infolog << "In HandleError";
        if(_inbuffer.EnableReadSize()>0){
            _message_callback(shared_from_this(),&_inbuffer);
        }
        Release();
    }
    void Connection::HandleEvent(){
        if(_enable_inactive_release==true) {_loop->TimerRefresh(_con_id);}
        if(_anyevent_callback){_anyevent_callback(shared_from_this());}
    }
    void Connection::EstablishInLoop(){
        // 建立连接后,要修改连接状态，设置可读事件，并且调用connet建立后的回调
        assert(_statu==CONNECTING);
        _statu= CONNECTED;
        _channel.EnableRead();
        if(_connected_callback){
            _connected_callback(shared_from_this());}
    }
    void Connection::ReleaseInLoop(){
        infolog<<"释放连接："<<_con_id;
        //1 修改连接状态
        // assert(_statu == DISCONNECTING);
        _statu = DISCONNECTED;
        //2 移除连接的监控事件
        _channel.Remove();
        //3 关闭文件描述符
        _socket.Close();
        //4 如果有定时销毁任务，那么取消它，判断方式一：
        if(_loop->HasTimer(_con_id)){
            CancelInactiveReleaseInLoop();}
        // 判断方式二：if(_enable_inactive_release==true) {CancelInactiveReleaseInLoop();} --错误
        // 因为即使标志为false，_loop也可能存在定时销毁任务
        //5 调用close连接回调函数（需要再svrclose之前，先移除用户的需求，再移除服务器的）
        if(_close_callback) {_close_callback(shared_from_this());}
        //6 再调用服务器连接回调函数（为防止服务器先移除掉Connection的连接信息，所以先执行关闭回调）
        if(_server_close_callback){_server_close_callback(shared_from_this());}
        
    }   
    void Connection::SendInLoop(Buffer& buf){
        if(_statu == DISCONNECTED) return;
        _outbuffer.WriteAsBufferAndPush(buf);
        if(_channel.WriterAble()==false){
            _channel.EnableWrite();
        }
    }
    // 并不直接关闭连接，处理还没有处理完的数据
    void Connection::ShutdownInLoop(){
        _statu = DISCONNECTING;
        if(_inbuffer.EnableReadSize()>0){
            _message_callback(shared_from_this(),&_inbuffer);
        }
        if(_outbuffer.EnableReadSize()>0){
            if(_channel.WriterAble()==false){
                _channel.EnableWrite();
            }
        }
        if(_outbuffer.EnableReadSize()==0)
            Release();
    }
    void Connection::EnableInactiveReleaseInLoop(int sec){
        // 将标志设置为true
        _enable_inactive_release=true;
        // 存在定时任务则刷新，不存在就创建
        if(_loop->HasTimer(_con_id)){return _loop->TimerRefresh(_con_id);}
        _loop->AddTimerTask(_con_id, sec, bind(&Connection::Release,this));
    }
    void Connection::CancelInactiveReleaseInLoop(){
        // 将标志设置为false
        _enable_inactive_release=false;
        // 直接取消定时器任务
        _loop->TimerCancel(_con_id);
    }
    // 更新上下文以及回调函数
    void Connection::UpgradeInLoop(const any& context,const ConnectedCallback& conc,const MessageCallback& mesc,const CloseCallback& closc,const AnyEventCallback& anyc){
        _context = context;
        _connected_callback=conc;
        _message_callback=mesc;
        _close_callback=closc;
        _anyevent_callback=anyc;
    }
    // ============================Connection public============================
    Connection::Connection(EventLoop* loop,uint64_t conid,int sock):_loop(loop),_con_id(conid),_sock(sock)\
                ,_channel(_loop,_sock),_enable_inactive_release(false),_statu(CONNECTING),_socket(_sock)
    {
        _channel.Set_read_callback(std::bind(&Connection::HandleRead,this));
        _channel.Set_write_callback(std::bind(&Connection::HandleWrite,this));
        _channel.Set_error_callback(std::bind(&Connection::HandleError,this));
        _channel.Set_close_callback(std::bind(&Connection::HandleClose,this));
        _channel.Set_event_callback(std::bind(&Connection::HandleEvent,this));
        // 不直接开启读事件监控？？？或者说为什么要在建立连接之后开启，而不在构造函数
        // 因为如果读事件直接开启，而立马被触发，此时还开启了非活跃连接销毁，但是此时还没有设置定时任务
    }
    bool Connection::Exist_message_callback(){
        if(_message_callback){
            return true;
        }
        return false;
    }
    int Connection::Fd(){return _sock;}
    uint64_t Connection::Id(){return _con_id;}
    bool Connection::Connected(){return _statu==CONNECTED;}
    void Connection::SetContext(const any& context){_context=context;}
    any* Connection::GetContext(){return &_context;}
    void Connection::SetConnectedCallback(const ConnectedCallback& conc){_connected_callback=conc;}
    void Connection::SetMessageCallback(const MessageCallback& mesc){_message_callback=mesc;}
    void Connection::SetCloseCallback(const CloseCallback& closc){_close_callback=closc;}
    void Connection::SetAnyEventCallback(const AnyEventCallback& anyc){_anyevent_callback=anyc;}
    void Connection::SetSvrCloseCallback(const CloseCallback& closc){_server_close_callback=closc;}
    void Connection::Establish(){
        _loop->RunLoop(bind(&Connection::EstablishInLoop,this));
    }
    void Connection::Release(){
        // 有可能在处理一个连接请求时，业务量非常大，导致处理完这个业务的时候别的连接超时了
        // 所以其它连接可能就被释放掉，导致在后续处理任务队列中任务的过程中，访问内存资源错误
        // 所以要将释放连接错误放到队列中
        _loop->PushTask(bind(&Connection::ReleaseInLoop,this));}
    void Connection::Send(const char* data,size_t len){
        Buffer buf;
        buf.WriteAndPush(data, len);
        _loop->RunLoop(bind(&Connection::SendInLoop,this,buf));
    }
    void Connection::Shutdown(){_loop->RunLoop(bind(&Connection::ShutdownInLoop,this));}
    void Connection::EnableInactiveRelease(int sec){_loop->RunLoop(bind(&Connection::EnableInactiveReleaseInLoop,this,sec));}
    void Connection::CancelInactive(){_loop->RunLoop(bind(&Connection::CancelInactiveReleaseInLoop,this));}
    void Connection::Upgrade(const any& context,const ConnectedCallback& conc,const MessageCallback& mesc,const CloseCallback& closc,const AnyEventCallback& anyc){_loop->RunLoop(bind(&Connection::UpgradeInLoop,this,context,conc,mesc,closc,anyc));}
    Connection::~Connection(){debuglog<<"RELEASE CONNECTION"<<this;}

}